const jsonwebtoken = require('jsonwebtoken')
const User = require('../models/users')
const Question = require('../models/questions')
const Answer = require('../models/answers')
const { SECRET } = require('../config')
class UsersCtl {
  // 授权中间件
  async checkOwner(ctx, next) {
    if (ctx.params.id !== ctx.state.user._id) {
      ctx.throw(403, '没有操作权限')
    }
    await next()
  }
  // 检查用户是否存在中间件
  async checkUserExist(ctx, next) {
    const user = await User.findById(ctx.params.id)
    if (!user) {
      ctx.throw(404, '该用户不存在')
    }
    await next()
  }
  // 获取用户列表
  async find(ctx) {
    const { per_page = 10 } = ctx.query
    // 当前页
    const page = Math.max(ctx.query.page * 1, 1) - 1
    // 每页显示多少条，同时防止小于1的情况
    const perPage = Math.max(per_page * 1, 1)
    ctx.body = await User.find({ name: new RegExp(ctx.query.q) })
      .limit(perPage)
      .skip(page * perPage)
  }
  // 获取指定用户
  async findById(ctx) {
    const { fields = '' } = ctx.query
    const selectedFields = fields
      .split(';')
      .filter(v => v)
      .map(v => ' +' + v)
      .join('')
    const populateStr = fields
      .split(';')
      .filter(v => v)
      .map(v => {
        if (v === 'employments') {
          return 'employments.company employments.job'
        } else if (v === 'educations') {
          return 'educations.school educations.major'
        } else {
          return v
        }
      })
      .join(' ')
    const user = await User.findById(ctx.params.id)
      .select(selectedFields)
      .populate(populateStr)
    ctx.body = user
  }
  // 注册用户
  async create(ctx) {
    ctx.verifyParams({
      name: { type: 'string', required: true },
      password: { type: 'string', required: true }
    })
    // 校验用户唯一性
    const { name } = ctx.request.body
    const repeatedUser = await User.findOne({ name })
    if (repeatedUser) {
      ctx.throw(409, '该用户名已注册')
    }
    const user = await new User(ctx.request.body).save()
    ctx.body = user
  }
  // 修改指定用户
  async update(ctx) {
    ctx.verifyParams({
      name: { type: 'string', required: false },
      password: { type: 'string', required: false },
      avatar_url: { type: 'string', required: false },
      gender: { type: 'string', required: false },
      headline: { type: 'string', required: false },
      locations: { type: 'array', itemType: 'string', required: false },
      business: { type: 'string', required: false },
      employments: { type: 'array', itemType: 'object', required: false },
      educations: { type: 'array', itemType: 'object', required: false }
    })
    const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
    ctx.body = user
  }
  // 删除指定用户
  async delete(ctx) {
    await User.findByIdAndRemove(ctx.params.id)
    ctx.status = 204
  }
  // 用户登录
  async login(ctx) {
    ctx.verifyParams({
      name: { type: 'string', required: true },
      password: { type: 'string', required: true }
    })
    const user = await User.findOne(ctx.request.body)
    if (!user) {
      ctx.throw(401, '用户名或密码不正确')
    }
    const { _id, name } = user
    const token = jsonwebtoken.sign({ _id, name }, SECRET, { expiresIn: '1d' })
    ctx.body = { token }
  }
  // 获取某个用户的关注人列表
  async listFollowing(ctx) {
    const user = await User.findById(ctx.params.id)
      .select('+following')
      .populate('following')
    ctx.body = user.following
  }
  // 获取某个用户的粉丝列表
  async listFollowers(ctx) {
    const users = await User.find({ following: ctx.params.id })
    ctx.body = users
  }
  // 关注某人
  async follow(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+following')
    if (!me.following.map(id => id.toString()).includes(ctx.params.id)) {
      me.following.push(ctx.params.id)
      me.save()
    }
    ctx.status = 204
  }
  // 取消关注某人
  async unfollow(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+following')
    const index = me.following.map(id => id.toString()).indexOf(ctx.params.id)
    if (index > -1) {
      me.following.splice(index, 1)
      me.save()
    }
    ctx.status = 204
  }
  // 获取某个用户的关注话题列表
  async listFollowingTopics(ctx) {
    const user = await User.findById(ctx.params.id)
      .select('+followingTopics')
      .populate('followingTopics')
    ctx.body = user.followingTopics
  }
  // 关注某个话题
  async followTopic(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+followingTopics'
    )
    if (!me.followingTopics.map(id => id.toString()).includes(ctx.params.id)) {
      me.followingTopics.push(ctx.params.id)
      me.save()
    }
    ctx.status = 204
  }
  // 取消关注某个话题
  async unfollowTopic(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+followingTopics'
    )
    const index = me.followingTopics
      .map(id => id.toString())
      .indexOf(ctx.params.id)
    if (index > -1) {
      me.followingTopics.splice(index, 1)
      me.save()
    }
    ctx.status = 204
  }
  // 获取某个用户的提问列表
  async listQuestions(ctx) {
    const questions = await Question.find({ questioner: ctx.params.id })
    ctx.body = questions
  }
  // 获取某个用户的关注问题列表
  async listFollowingQuestions(ctx) {
    const user = await User.findById(ctx.params.id)
      .select('+followingQuestions')
      .populate('followingQuestions')
    ctx.body = user.followingQuestions
  }
  // 关注某个问题
  async followQuestion(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+followingQuestions'
    )
    if (
      !me.followingQuestions.map(id => id.toString()).includes(ctx.params.id)
    ) {
      me.followingQuestions.push(ctx.params.id)
      me.save()
    }
    ctx.status = 204
  }
  // 取消关注某个问题
  async unfollowQuestion(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+followingQuestions'
    )
    const index = me.followingQuestions
      .map(id => id.toString())
      .indexOf(ctx.params.id)
    if (index > -1) {
      me.followingQuestions.splice(index, 1)
      me.save()
    }
    ctx.status = 204
  }
  // 获取某个用户点赞的答案列表
  async listLikingAnswers(ctx) {
    const user = await User.findById(ctx.params.id)
      .select('+likingAnswers')
      .populate('likingAnswers')
    ctx.body = user.likingAnswers
  }
  // 点赞某个答案
  async likeAnswer(ctx, next) {
    const me = await User.findById(ctx.state.user._id).select('+likingAnswers')
    if (!me.likingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
      me.likingAnswers.push(ctx.params.id)
      me.save()
      // 答案模型中点赞数+1
      await Answer.findByIdAndUpdate(ctx.params.id, { $inc: { voteCount: 1 } })
    }
    ctx.status = 204
    await next()
  }
  // 取消点赞某个答案
  async unlikeAnswer(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+likingAnswers')
    const index = me.likingAnswers
      .map(id => id.toString())
      .indexOf(ctx.params.id)
    if (index > -1) {
      me.likingAnswers.splice(index, 1)
      me.save()
      // 答案模型中点赞数-1
      // const answer = await Answer.findById(ctx.params.id)
      // if (answer.voteCount >= 1) {
      //   answer.update({ $inc: { voteCount: -1 } })
      // }
      await Answer.findByIdAndUpdate(ctx.params.id, { $inc: { voteCount: -1 } })
    }
    ctx.status = 204
  }
  // 获取某个用户点踩的答案列表
  async listDislikingAnswers(ctx) {
    const user = await User.findById(ctx.params.id)
      .select('+dislikingAnswers')
      .populate('dislikingAnswers')
    ctx.body = user.dislikingAnswers
  }
  // 点踩某个答案
  async dislikeAnswer(ctx, next) {
    const me = await User.findById(ctx.state.user._id).select(
      '+dislikingAnswers'
    )
    if (!me.dislikingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
      me.dislikingAnswers.push(ctx.params.id)
      me.save()
    }
    ctx.status = 204
    await next()
  }
  // 取消点踩某个答案
  async undislikeAnswer(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+dislikingAnswers'
    )
    const index = me.dislikingAnswers
      .map(id => id.toString())
      .indexOf(ctx.params.id)
    if (index > -1) {
      me.dislikingAnswers.splice(index, 1)
      me.save()
    }
    ctx.status = 204
  }
  // 获取某个用户收藏的答案列表
  async listCollectingAnswers(ctx) {
    const user = await User.findById(ctx.params.id)
      .select('+collectingAnswers')
      .populate('collectingAnswers')
    ctx.body = user.collectingAnswers
  }
  // 收藏某个答案
  async collectAnswer(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+collectingAnswers'
    )
    if (!me.collectingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
      me.collectingAnswers.push(ctx.params.id)
      me.save()
    }
    ctx.status = 204
  }
  // 取消收藏某个答案
  async uncollectAnswer(ctx) {
    const me = await User.findById(ctx.state.user._id).select(
      '+collectingAnswers'
    )
    const index = me.collectingAnswers
      .map(id => id.toString())
      .indexOf(ctx.params.id)
    if (index > -1) {
      me.collectingAnswers.splice(index, 1)
      me.save()
    }
    ctx.status = 204
  }
}
module.exports = new UsersCtl()
